package application;

import java.util.HashMap;
import java.util.Vector;

import org.omg.CORBA.ORB;
import org.omg.CORBA.Object;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.NotFound;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;


import namingService.AMI_ClientHandler;
import namingService.AMI_ServerHandler;
import namingService.Client;
import namingService.ClientHelper;
import namingService.Server;
import namingService.ServerPOA;
import namingService._ClientStub;
import namingService._ServerStub;

public class LeafServer extends ServerPOA{

	private Vector<EntityNaming> LocationRecord = null;
	private HashMap<String, Integer> IndexName = null;
	private Server father = null;
	private ORB orb = null;
	private AMI_ServerHandler sh = null;
	private AMI_ClientHandler ch = null;
	
	public LeafServer(){
		LocationRecord = new Vector<EntityNaming>();
		IndexName = new HashMap<String, Integer>();	
	}
	
	public synchronized void insertEntity(String name, String address) {
		EntityNaming e = new EntityNaming(name, address);
		
		if (IndexName.get(name) == null){
			((_ServerStub) father).sendc_insertEntity(sh, name, orb.object_to_string(_this()));
			IndexName.put(name, new Integer(0));
		}
		IndexName.put(name, IndexName.get(name)+1);
		LocationRecord.add(e);
		
	}

	public synchronized void removeEntity(String name, String address) {
		
		EntityNaming e = new EntityNaming(name,address);
		
		if (IndexName.get(name)!=null && LocationRecord.contains(e)){
			if (IndexName.get(name) < 2){
				((_ServerStub) father).sendc_removeEntity(sh, name,orb.object_to_string(_this()));
				IndexName.remove(name);
			}else {
				IndexName.put(name, IndexName.get(name)-1);
			}
			
			LocationRecord.remove(e);
			
			
		}
		
	}

	public synchronized void searchEntity(String name, String requester) {
		if (IndexName.get(name)!=null){	
			for (int i =0 ; i < LocationRecord.size();i++){
				if (LocationRecord.get(i).getName().equals(name)){
					org.omg.CORBA.Object obj = orb.string_to_object(requester);
					Client cli = ClientHelper.narrow(obj);
					((_ClientStub)cli).sendc_messageToClient(ch,LocationRecord.get(i).toString());
				}
			}
		} else {
			((_ServerStub) father).sendc_searchEntity(sh, name, requester);
		}
	}
	
	private void setAttributes(ORB orb2, Server father2, AMI_ServerHandler sh2,
			AMI_ClientHandler ch2) {
	
		orb = orb2;
		father = father2;
		sh = sh2;
		ch = ch2;
	}

	public static void main(String[] args){
		
		if (args.length<6){
		
			System.out.println("Required arguments: -ORBInitialPort #port -ORBInitialHost #IP leafname fathername");
			System.exit(1);
		}
		
		try {
			LeafServer ln = new LeafServer();
			
			Server father = null;
			ORB orb = null;
			AMI_ServerHandler sh = null;
			AMI_ClientHandler ch = null;
			
			String orbconf[] = {args[0], args[1], args[2], args[3]};
			orb = ORB.init(orbconf, null);
			POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
			rootPOA.the_POAManager().activate();
			org.omg.CORBA.Object Lref = rootPOA.servant_to_reference(ln);
			
			Object objRef = orb.resolve_initial_references("NameService");
			NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
			
			NameComponent pathLeaf[] = ncRef.to_name("Servers/LeafServers/"+args[4]);
	        ncRef.rebind(pathLeaf, Lref);
	        System.out.println(args[4]+" added...");
	        
	        ch = new AMI_ClientHandlerImpl()._this(orb);
	        
	    	NameComponent fatherN[] = ncRef.to_name("Servers/DirectoryServers/"+args[5]);
	    	org.omg.CORBA.Object fatherObj;
			fatherObj = ncRef.resolve(fatherN);
			father = namingService.ServerHelper.narrow(fatherObj);
			
			sh = new AMI_ServerHandlerImpl()._this(orb);
	        
			ln.setAttributes(orb,father,sh,ch);
			
	        orb.run();
		} catch (NotFound e) {
			e.printStackTrace();
			System.exit(1);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		} 
    	
    	
		
	}
	

}
